import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import socket
import threading

class SocketServerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("Socket服务器")
        self.root.geometry("600x500")
        
        # Socket相关变量
        self.server_socket = None
        self.running = False
        self.clients = []
        
        self.setup_ui()
        
    def setup_ui(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 服务器设置区域
        server_frame = ttk.LabelFrame(main_frame, text="服务器设置", padding="10")
        server_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        ttk.Label(server_frame, text="监听地址:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))
        self.host_entry = ttk.Entry(server_frame, width=20)
        self.host_entry.insert(0, "localhost")
        self.host_entry.grid(row=0, column=1, padx=(0, 10))
        
        ttk.Label(server_frame, text="端口:").grid(row=0, column=2, sticky=tk.W, padx=(0, 5))
        self.port_entry = ttk.Entry(server_frame, width=10)
        self.port_entry.insert(0, "12345")
        self.port_entry.grid(row=0, column=3, padx=(0, 10))
        
        self.start_btn = ttk.Button(server_frame, text="启动服务器", command=self.start_server)
        self.start_btn.grid(row=0, column=4, padx=(0, 5))
        
        self.stop_btn = ttk.Button(server_frame, text="停止服务器", command=self.stop_server, state=tk.DISABLED)
        self.stop_btn.grid(row=0, column=5)
        
        # 客户端连接显示区域
        client_frame = ttk.LabelFrame(main_frame, text="客户端连接", padding="10")
        client_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        self.client_listbox = tk.Listbox(client_frame, height=5)
        self.client_listbox.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 消息显示区域
        message_frame = ttk.LabelFrame(main_frame, text="消息记录", padding="10")
        message_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        self.message_text = scrolledtext.ScrolledText(message_frame, height=12, width=70)
        self.message_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)
        main_frame.rowconfigure(2, weight=1)
        client_frame.columnconfigure(0, weight=1)
        client_frame.rowconfigure(0, weight=1)
        message_frame.columnconfigure(0, weight=1)
        message_frame.rowconfigure(0, weight=1)
        
    def start_server(self):
        if not self.running:
            try:
                host = self.host_entry.get().strip()
                port = int(self.port_entry.get().strip())
                
                self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.server_socket.bind((host, port))
                self.server_socket.listen(5)
                
                self.running = True
                self.start_btn.config(state=tk.DISABLED)
                self.stop_btn.config(state=tk.NORMAL)
                
                self.add_message(f"服务器已启动，监听 {host}:{port}")
                
                # 启动接受连接线程
                self.accept_thread = threading.Thread(target=self.accept_connections)
                self.accept_thread.daemon = True
                self.accept_thread.start()
                
            except Exception as e:
                messagebox.showerror("启动错误", f"启动服务器失败: {e}")
                self.add_message(f"启动服务器失败: {e}")
    
    def stop_server(self):
        if self.running:
            try:
                self.running = False
                if self.server_socket:
                    self.server_socket.close()
                
                # 关闭所有客户端连接
                for client_socket in self.clients:
                    try:
                        client_socket.close()
                    except:
                        pass
                
                self.clients.clear()
                
                self.start_btn.config(state=tk.NORMAL)
                self.stop_btn.config(state=tk.DISABLED)
                self.client_listbox.delete(0, tk.END)
                
                self.add_message("服务器已停止")
                
            except Exception as e:
                self.add_message(f"停止服务器失败: {e}")
    
    def accept_connections(self):
        while self.running:
            try:
                client_socket, addr = self.server_socket.accept()
                self.clients.append(client_socket)
                
                # 更新客户端列表
                self.root.after(0, lambda: self.client_listbox.insert(tk.END, str(addr)))
                self.add_message(f"新客户端连接: {addr}")
                
                # 为每个客户端创建处理线程
                client_handler = threading.Thread(
                    target=self.handle_client,
                    args=(client_socket, addr)
                )
                client_handler.daemon = True
                client_handler.start()
                
            except Exception as e:
                if self.running:
                    self.add_message(f"接受连接错误: {e}")
                break
    
    def handle_client(self, client_socket, addr):
        try:
            while True:
                data = client_socket.recv(1024)
                if not data:
                    break
                message = data.decode('utf-8')
                self.add_message(f"从 {addr} 收到: {message}")
                
                # 回复客户端
                response = f"服务器收到: {message}"
                client_socket.send(response.encode('utf-8'))
                
        except Exception as e:
            self.add_message(f"处理客户端 {addr} 错误: {e}")
        finally:
            try:
                # 从客户端列表中移除
                if client_socket in self.clients:
                    self.clients.remove(client_socket)
                
                # 从列表框中移除
                self.root.after(0, lambda: self.remove_client_from_list(str(addr)))
                
                client_socket.close()
                self.add_message(f"与 {addr} 的连接已关闭")
            except:
                pass
    
    def remove_client_from_list(self, addr_str):
        items = self.client_listbox.get(0, tk.END)
        for i, item in enumerate(items):
            if item == addr_str:
                self.client_listbox.delete(i)
                break
    
    def add_message(self, message):
        self.message_text.insert(tk.END, f"{message}\n")
        self.message_text.see(tk.END)
        self.message_text.update()

def main():
    root = tk.Tk()
    app = SocketServerGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()